<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // 用常量 定义的状态,避免后续  硬编码(代码中写死某个值)
    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'

    // 定义类
    class MyPromise {
      // 状态
      state = PENDING
      // 结果 成功/失败
      result = undefined

      // 异步的回调函数 [{onFulfilled,onRejected,resolve,reject}]
      #handlers = []

      // 构造函数,resolve定义,reject定义,执行传入的回调函数
      constructor(executor) { // new MyPromise((resolve,reject)=>{ console.log('立刻执行') })
        const resolve = (result) => {
          // 修改状态+执行保存的回调函数
          this.#changeState(FULFILLED, result)
          this.#runHandlers()
        }
        const reject = (result) => {
          // 修改状态+执行保存的回调函数
          this.#changeState(REJECTED, result)
          this.#runHandlers()
        }
        executor(resolve, reject)
      }

      // 执行回调函数,取出数组中的回调函数,执行到没有为止
      #runHandlers() {
        // 循环执行到数组长度为0为止
        while (this.#handlers.length > 0) {
          const { onFulfilled, onRejected, resolve, reject } = this.#handlers.shift()// unshift
          if (this.state === FULFILLED) { // this.state='fulfilled'
            // 成功 执行 和 then中类似的逻辑
            // 获取结果,根据是否为Promise以及状态调用对应的逻辑
            //  onFulfilled(this.result)
            this.#runPromise(onFulfilled, resolve, reject)
          } else if (this.state === REJECTED) {
            // 失败
            // onRejected(this.result)
            this.#runPromise(onRejected, resolve, reject)
          }
        }
      }

      // 改变状态(pending时才可以修改,保存成功/失败的结果)
      #changeState(state, result) {
        if (this.state !== PENDING) {
          return
        }
        this.state = state
        this.result = result
      }

      // 获取回调函数的结果,根据类型执行不同的逻辑
      #runPromise(callBack, resolve, reject) {
        queueMicrotask(() => {
          try {
            // 调用回调函数 获取执行的结果
            const res = callBack(this.result)
            if (res instanceof MyPromise) {
              // res是Promise对象 then方法
              res.then(resolve, reject)
            } else {
              // 如果是普通的值,直接resolve
              if (this.state === FULFILLED) {
                resolve(res)
              } else if (this.state === REJECTED) {
                reject(res)
              }
            }
          } catch (error) {
            // console.log('catch:', error)
            reject(error)
          }

        })

      }

      // 链式编程 promise对象.then(xxx).then(xxx)
      then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => x // function(x){ return x }
        onRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x } // function(x){ throw x }

        // 1. 创建一个新的Promise对象 并返回
        const p2 = new MyPromise((resolve, reject) => {
          if (this.state === FULFILLED) {
            this.#runPromise(onFulfilled, resolve, reject)
          } else if (this.state === REJECTED) {
            this.#runPromise(onRejected, resolve, reject)
          } else {
            // pending状态(状态还没改变,回调函数还不能执行)
            // 以对象的形式保存回调函数,成功和失败都保存了
            this.#handlers.push({
              onFulfilled, onRejected, resolve, reject
            })
          }
        })

        return p2
      }

      // 实例方法-catch 本质 then(undefined,onRejected)
      catch(onRejected) {
        return this.then(undefined, onRejected)
      }

      // 实例方法-finally 
      finally(onFinally) {
        // 将传入的回调函数,作为成功/失败的回调函数
        // 成功/失败都会执行
        return this.then(onFinally, onFinally)
      }

      // 静态方法 resolve 返回成功状态的Promise
      // 根据传入的值,返回不同的结果即可
      static resolve(value) {
        if (value instanceof MyPromise) {
          // MyPromise的实例,直接返回,后续即可链式调用
          return value
        }
        // 其他的值,返回一个新的MyPromise对象
        return new MyPromise((resolve, reject) => {
          resolve(value)
        })

      }

      // 静态方法 reject 返回失败状态的Promise
      static reject(value) {
        return new MyPromise((resolve, reject) => {
          reject(value)
        })
      }

      // 静态方法 race 
      static race(promises) {
        // race的后面需要.then.catch
        return new MyPromise((resolve, reject) => {
          // 传入的是数组才继续执行
          if (Array.isArray(promises)) {
            // 是数组 解析
            promises.forEach(p => {
              // MyPromise.resolve 传入的无论是不是Promise->Promise
              MyPromise.resolve(p).then(resolve, reject)
              // 如果不处理,传入普通的值,会直接报错
              // p.then(resolve, reject)
            })
          } else {
            // 不是数组 失败
            reject(new Error('object is not iterable'))
          }
        })
      }

      // 静态方法 all
      static all(promises) {
        // 外部可以 then catch
        return new MyPromise((resolve, reject) => {
          if (Array.isArray(promises)) {
            // 数组-继续解析
            // 空数组-直接成功
            if (promises.length === 0) {
              resolve(promises) // []
            }
            // 挨个解析
            const results = []
            // 记录结果的个数,判断是否完结
            let count = 0
            promises.forEach((p, index) => {
              // 普通值 记录结果 并判断是否成功
              if (p instanceof MyPromise) {
                // Promise对象
                p.then(res => {
                  // 保证结果的顺序 和Promise数组的顺序一致
                  results[index] = res
                  count++
                  count === promises.length && resolve(results)
                }, err => {
                  // 任何一个失败,直接失败
                  reject(err)
                })
              } else {
                // 普通值 保证结果的顺序 和Promise数组的顺序一致
                results[index] = p
                count++
                // count===promises.length 解析完毕
                count === promises.length && resolve(results)
              }
            })

          } else {
            // 不是数组-直接报错
            reject(new Error('object is not iterable'))
          }
        })
      }

      // 静态方法 allSettled
      static allSettled(promises) {
        return new MyPromise((resolve, reject) => {
          if (Array.isArray(promises)) {
            // 返回一个新的Promise对象
            // 数组->解析
            // 长度为0->成功
            if (promises.length === 0) {
              resolve([])
            } else {
              const results = []
              let count = 0
              promises.forEach((p, index) => {
                p.then(res => {
                  // {value:'xx',status:'fulfilled'}
                  results[index] = {
                    value: res,
                    status: FULFILLED
                  }
                  count++
                  count === promises.length && resolve(results)
                }, err => {
                  // {reason:'xx',status:'rejected'}
                  results[index] = {
                    reason: err,
                    status: REJECTED
                  }
                  count++
                  count === promises.length && resolve(results)
                })
              })
            }
            // 长度不为0->挨个解析 成功/失败,按照成功解析(包装到对象中)
          } else {
            // 不是数组->报错
            reject(new Error('object is not iterable'))
          }
        })
      }

      // 静态方法 any
      static any(promises) {
        return new MyPromise((resolve, reject) => {
          if (Array.isArray(promises)) {
            // 数组判断-是
            // 长度0-成功
            if (promises.length === 0) {
              resolve(promises)
            }
            // 长度不为0 挨个解析
            const errs = []
            let count = 0
            promises.forEach((p, index) => {
              p.then(res => {
                // 只要成功 直接 resolve
                resolve(res)
              }, err => {
                // 都失败
                errs[index] = err
                count++
                // 是否都失败
                promises.length === count && reject(new AggregateError(errs))
              })
            })

          } else {
            // 数组判断-不是
            reject(new Error('object is not iterable'))
          }
        })
      }
    }

    // ------------- 测试 any -------------
    // 传入Promises数组
    // 任何一个成功,即可获取成功结果
    // 所有的都失败了,直接失败,
    const promise1 = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        reject('error1')
      }, 2000);
    });
    const promise2 = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        // resolve('success2')
        reject('error2')
      }, 3000);
    });
    const promise3 = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        // resolve('success1')
        reject('error3')
      }, 1000);
    });

    MyPromise.any([promise1, promise2, promise3]).then((values) => {
      console.log(values);
    }, err => {
      // AggregateError: All promises were rejected
      // AggregateError 内置的错误对象 new AggregateError([])并传入错误原因即可
      // console.log('err:', err)
      console.dir(err)
    })

    // ------------- 测试 allSettled -------------
    // 获取传入的Promise数组 的 敲定状态 和结果
    // 包装到对象中{value:'成功的值',reason:'失败原因',status:'状态'}
    // const promise1 = MyPromise.resolve('1');
    // const promise2 = new MyPromise((resolve, reject) => setTimeout(() => {
    //   reject('two')
    // }, 1000));
    // const promise3 = new MyPromise((resolve, reject) => setTimeout(() => {
    //   resolve('three')
    // }, 3000));
    // const promises = [promise1, promise2, promise3];

    // MyPromise.allSettled(promises).then((results) => { console.log(results) }, err => {
    //   console.log(err)
    // })

    // ------------- 测试 all -------------
    // const promise1 = MyPromise.resolve(3);
    // const promise2 = 42;
    // const promise3 = new MyPromise((resolve, reject) => {
    //   setTimeout(() => {
    //     // resolve('success')
    //     reject('error')
    //   }, 1000);
    // });

    // // MyPromise.all([1, 2, 3, 4, 5]).then((values) => {
    // // MyPromise.all([]).then((values) => {
    // // MyPromise.all(promise1).then((values) => {
    // MyPromise.all([promise1, promise2, promise3]).then((values) => {
    //   console.log(values);
    // }, err => {
    //   console.log('err:', err)
    // });

    // ------------- 测试 race -------------
    // 传入Promise数组,第一个成功/失败 就会执行对应的回调函数
    // const promise1 = new MyPromise((resolve, reject) => {
    //   setTimeout(() => {
    //     resolve('one')
    //   }, 5000)
    // })

    // const promise2 = new MyPromise((resolve, reject) => {
    //   setTimeout(() => {
    //     reject('two')
    //   }, 1000)
    // })

    // // MyPromise.race(promise1).then((value) => {
    // MyPromise.race([promise1, promise2, 2]).then((value) => {
    //   console.log('value:', value)
    // }, err => {
    //   console.log('err:', err)
    // })

    // ------------- 测试 -------------
    // MyPromise.reject('滚犊子!').catch(error => {
    //   console.log('error:', error)
    // })
    // const p = new MyPromise((resolve, reject) => {
    //   resolve('Promise内部的resolve')
    // })

    // MyPromise.resolve(p).then(res => {
    //   console.log('res:', res)
    // })
  </script>
</body>

</html>